package com.apes.fn.server.servicePlan.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.pi.fnCommunal.FnCommunalService;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.Model;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.car.model.CarConfiguration;
import com.apes.scm.masterdata.car.repository.CarConfigurationRepository;
import com.apes.scm.masterdata.frame.model.Channel;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.ChannelRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.AccessProviderRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.service.LocationService;
import com.apes.scm.rbac.model.Post;
import com.apes.scm.rbac.repository.PostRepository;

import java.util.*;

/**
 * @program: apes-server
 * @description 服务方案建造者实现
 * @author: czs
 * @create: 2022-05-08 09:45
 **/
public class ServicePlanBuilder extends AbstractPlan implements PlanBuilder {

    ServicePlan servicePlan = new ServicePlan();

    private PartyRole person = null;

    private Post post = null;

    private String carLicense;

    private String state;

    private Map<String,JSONObject> items = new HashMap();

    /**
     * 需要初始化属性,所以私有无参构造
     */
    private ServicePlanBuilder() {
    }

    /**
     * 初始化属性
     *
     * @param request
     */
    public ServicePlanBuilder(SimpleRequest request) {

        initialize(request);
        checkInitialize();

    }

    /**
     * 初始化
     * @param person
     * @param post
     */
    public ServicePlanBuilder(PartyRole person,Post post) {
        this.person = person;
        this.post = post;
        checkInitialize();

    }

    /**
     * 初始化方法
     *
     * @param request
     */
    private void initialize(SimpleRequest request) {
        setUserInfo(request);
    }

    public ServicePlanBuilder setCarLicense(String carLicense) {
        this.carLicense = carLicense;
        return this;
    }


    public ServicePlanBuilder setState(String state) {
        this.state = state;
        return this;
    }

    public ServicePlanBuilder setItems(Map<String,JSONObject> items) {
        this.items = items;
        return this;
    }
    public ServicePlanBuilder setItems(List<JSONObject> servicePlanItemsJson) {
        servicePlanItemsJson.forEach(jo -> items.put(jo.getJSONObject("product").getString("id"),jo));
        return this;
    }
    public void checkItemsCondition(JSONObject jsonObject){
        boolean product = jsonObject.containsKey("product");
        if (!product)throw new RuntimeException("创建明细入参,缺少商品对象");
//        boolean saleQty = jsonObject.containsKey("saleQty");
//        if (!saleQty)throw new RuntimeException("创建明细入参,缺少商品数量");
    }

    /**
     * 检查初始化是否成功
     */
    private void checkInitialize() {
        if (this.person == null) throw new RuntimeException("初始化获取人员失败");
        if (this.post == null) throw new RuntimeException("初始化获取岗位失败");
    }

    @Override
    public void setUserInfo(SimpleRequest request) {
        this.person = (PartyRole) request.getPerson();
        this.post = SpringManager.getBean(PostRepository.class).findOne(request.getPostId());

    }

    @Override
    public ServicePlanBuilder buildBody() {
        //1.构建默认信息
        servicePlan.setServeType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne("ServicePlan.serveType.A"));
        servicePlan.setState("create");
        servicePlan.setChannel(SpringManager.getBean(ChannelRepository.class).findOne("10"));
        //2.构建方案三个部门
        Dept belongDept = post.getDept();
        if (belongDept==null)throw new RuntimeException("当前登录角色无部门信息");
        servicePlan.setBelongDept(belongDept);
        servicePlan.setServiceDept(belongDept);
        servicePlan.setSaleDept(belongDept);
        //3.构建车辆信息
        //3.1 获取接入商
        String accessProvider = SpringManager.getBean(AccessProviderRepository.class).findByCompany(belongDept.getCompany().getId()).getId();
        JSONObject customerCar = invoke("fn.customerCar.findOne", MapUtil.mapper("carLicense", carLicense, "vendorCode", accessProvider));
        if (customerCar == null || customerCar.isEmpty()) throw new RuntimeException("无效车牌:" + carLicense);
        JSONObject customer = this.invoke("fn.customer.findOne", MapUtil.mapper("vendorCode", accessProvider, "mobile", customerCar.get("mobile")));
        servicePlan.setFnCustomerExpand(
                findFnCustomerExpandAndSave(belongDept, customer, customerCar)
        );
        try{
            FnCustomerExpand fnCustomerExpand = servicePlan.getFnCustomerExpand();
            String jekunModelCode = fnCustomerExpand.getJekunModelCode();
            CarConfiguration carConfiguration = SpringManager.getBean(CarConfigurationRepository.class).findOne(jekunModelCode);
            servicePlan.setCarLabel(carConfiguration.getCarLabel());
            servicePlan.setCarModel(carConfiguration.getCarModel());
            servicePlan.setCarConfiguration(carConfiguration);
        } catch(Exception e) {
            throw new RuntimeException("获取车型信息出错,错误信息:"+e.getMessage());
        }
        //4.构建人员信息
        servicePlan.setOperator1(person);
        return this;
    }

    @Override
    public ServicePlanBuilder buildItems() {
        if (servicePlan.getBelongDept() == null) throw new RuntimeException("请先构建主表信息再添加商品");
        List<ServicePlanItem> servicePlanItems = new ArrayList<>();
        ProductRepository productRepository = SpringManager.getBean(ProductRepository.class);
        Object mapped = MapUtil.mapped(servicePlan);
        for (Object o : items.entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            String productId = (String) entry.getKey();
            JSONObject jo = (JSONObject) entry.getValue();
            Product product = productRepository.findOne(productId);
            if (jo.getString("oldInquiryNumber")!=null){
                servicePlanItems.add(createEmptyPlanItem(servicePlan,product,findProductLocation(product)));
            }else {
                double qty = jo.containsKey("saleQty")?jo.getDoubleValue("saleQty"):1;
                //查找商品价格信息
                JSONObject planItem = this.invoke("fn.service.getPrise", MapUtil.mapper("condition", MapUtil.mapped(product), "conditionModel", mapped));
                ServicePlanItem servicePlanItem = JSONObject.toJavaObject(planItem, ServicePlanItem.class);
                //添加数量 计算金额
                servicePlanItem.setSaleQty(qty);
                servicePlanItem.setPrimaryPriceUnitShow(servicePlanItem.getPrimaryPriceUnit());
                servicePlanItem.setSalesAmount(qty * servicePlanItem.getPftPriceUnit());
                servicePlanItem.setDiscountRate(servicePlanItem.calculateDiscountRate());
                servicePlanItems.add(servicePlanItem);
            }

        }
        servicePlan.setServicePlanItems(servicePlanItems);
        return this;

    }

    @Override
    public ServicePlanBuilder changeState() {
        switch (state) {
            case "create":
                servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
                break;
            case "submission":
                servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
                servicePlan.getServicePlanItems().forEach(servicePlanItem -> servicePlanItem.setMainSaler(person));
                servicePlan = this.invoke("fn.service.submissionForInvoke", MapUtil.mapped(servicePlan));
                break;
            case "confirm":
                servicePlan = this.invoke("fn.service.createForInvoke", MapUtil.mapped(servicePlan));
                servicePlan.getServicePlanItems().forEach(servicePlanItem -> servicePlanItem.setMainSaler(person));
                servicePlan = this.invoke("fn.service.submissionForInvoke", MapUtil.mapped(servicePlan));
                servicePlan = this.invoke("fn.service.confirmForInvoke", MapUtil.mapped(servicePlan));
                break;
            default:
                throw new RuntimeException("未知状态");
        }
        return this;

    }

    @Override
    public Model buildPlan() {
        if (servicePlan.getBelongDept() == null) throw new RuntimeException("请先构建主表信息再添加商品");
        if (servicePlan.getServicePlanItems().isEmpty()) throw new RuntimeException("请添加商品信息");
        return this.servicePlan;
    }

    /**
     * 查找仓库
     * @param product
     * @return
     */
    private Location findProductLocation(Product product){
        Location location;
        try {
            Dept belongDept = servicePlan.getBelongDept();

            Boolean productRule = findProductRule(product);
            //查找库存
            location = SpringManager.getBean(LocationService.class).findLocationByDept(belongDept, productRule);
            if (productRule) {
                if (location == null) throw new RuntimeException("门店没有设置带安虚拟库，门店名称：" + belongDept.getName());
            } else {
                if (location == null) throw new RuntimeException("未找到门店对应的仓库" + belongDept.getName());
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return location;
    }

    /**
     * 查找带安规则
     * @param product
     * @return
     */
    private Boolean findProductRule(Product product){
        Dept belongDept = servicePlan.getBelongDept();
        //查找带安规则
        boolean productRule = ((List) this.invoke("cm.consignmentRule.findAllByCategoryAndProvinceAndCity",
                MapUtil.mapper("deptId", belongDept.getId(),
                        "categoryId", product.getCategory().getId(), "brandId", product.getBrand().getId())
        )).size() != 0;
        return productRule;
    }
    public ServicePlan fastBuildServicePlan() {
        buildBody();
        buildItems();
        changeState();
        return this.servicePlan;
    }
    public ServicePlanBuilder setNote(String sourceFrom,String sourceBusinessType, String sourceBusinessTypeName) {
        servicePlan.setSourceFrom(sourceFrom);
        servicePlan.setSourceBusinessType(sourceBusinessType);
        servicePlan.setSourceBusinessTypeName(sourceBusinessTypeName);
        return this;
    }

    public ServicePlanBuilder changeChannel(String channelId) {
        servicePlan.setChannel(SpringManager.getBean(ChannelRepository.class).findOne(channelId));
        return this;
    }

    public ServicePlanItem createEmptyPlanItem(ServicePlan servicePlan, Product product, Location location){
        ServicePlanItem servicePlanItem = new ServicePlanItem();
        Double amount = 0D;
        servicePlanItem.setPrimaryPriceUnit(amount);
        servicePlanItem.setBasePrice(amount);
        servicePlanItem.setPriceUnit(amount);
        PartyRole platform = SpringManager.getBean(FnCommunalService.class).getPlatform(false, true, servicePlan.getBelongDept(), product);
        servicePlanItem.setPlatform(platform);
        servicePlanItem.setPrimaryPriceUnitShow(amount);
        servicePlanItem.setPftPriceUnit(amount);
        servicePlanItem.setClerkPriceLimit(amount);
        servicePlanItem.setShopOwnerPriceLimit(amount);
        servicePlanItem.setCsoPriceLimit(amount);
        servicePlanItem.setSalesAmount(amount);
        servicePlanItem.setProduct(product);
        servicePlanItem.setSaleQty(1);
        servicePlanItem.setLocation(location);
        servicePlanItem.setFloorPrice(0);
        servicePlanItem.setPlatformPriceCosInTax(0);
        servicePlanItem.setPriceCostUnitInTax(0);
        servicePlanItem.setPriceCostUnitExTax(0);
        servicePlanItem.setManagementFeeRate(0);
        servicePlanItem.setUom(product.getUom());
        servicePlanItem.setManagementCost(0);
        servicePlanItem.setCategory(product.getCategory());
        // servicePlanItem.setExpectedArrivalTime(0);
        // servicePlanItem.setInquiryGooodsState();
        // servicePlanItem.setReferTax(item.getReferTax());
        // servicePlanItem.setSupplyChainManagement(item.getSupplyChainManagement());
        // servicePlanItem.setEstimatedCommission(item.getEstimatedCommission());
        // servicePlanItem.setOldInquiryNumber(item.getOldInquiryNumber());
//        servicePlanItem.setServicePlan(servicePlan);
//        servicePlan.getServicePlanItems().add(servicePlanItem);
        return servicePlanItem;
    }
}
